## -*- coding: utf-8 -*-
import datetime
from dateutil import relativedelta
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django_extensions.db.fields import CreationDateTimeField, ModificationDateTimeField, UUIDField
from tastypie.models import create_api_key

datetime_now = datetime.datetime.now

class BaseModel(models.Model):
    created_on = CreationDateTimeField(_('Created on'))
    updated_on = ModificationDateTimeField(_('Updated on'))

    comment = models.TextField(_('Comment'), blank=True)
    uuid = UUIDField(_('UUID'), version=4)
    ext_info = models.TextField(_('Ext Json'), default='{}')

    class Meta:
        abstract = True

# tommy Documents
class Documents(BaseModel):
    file_name = models.CharField(_('File Name'), max_length=255, null=True, blank=True, db_index=True)
    file_path = models.FileField(_('File Path'), upload_to='uploads/', max_length=255)

    class Meta:
        ordering = ['-id']
        db_table = 'erp_documents'

# tommy: MyUserProfile 用户扩展信息表
class Profile(BaseModel):
    GENDER_CHOICES = (
        ('male', _('male')),
        ('female', _('female')),
    )
    # This field is required.
    user = models.OneToOneField(User)
    # Other fields here
    phone = models.CharField(_('Phone'), max_length=255, blank=True, db_index=True)

    gender = models.CharField(_('Gender'), max_length=255, choices=GENDER_CHOICES, default='male')
    birthday = models.DateField(_('Birthday'), blank=True, null=True, db_index=True)
    identity_card = models.CharField(_('Identity Card'), max_length=255, blank=True, db_index=True)
    address = models.CharField(_('Address'), max_length=255, blank=True, db_index=True)

    @property
    def age(self):
        TODAY = timezone.now()
        return u'%s' % relativedelta.relativedelta(TODAY, self.birthday).years

    class Meta:
        db_table = 'user_profile'


def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)
post_save.connect(create_api_key, sender=User)


############## company #########################################
class Company(BaseModel):
    company_name = models.CharField(_('Company Name'), max_length=255, blank=True, db_index=True)
    address = models.CharField(_('Address'), max_length=255, blank=True, db_index=True)
    city = models.CharField(_('City'), max_length=255, blank=True, db_index=True)
    state = models.CharField(_('State'), max_length=255, blank=True, db_index=True)
    postal_code = models.CharField(_('Postal Code'), max_length=255, blank=True, db_index=True)
    country = models.CharField(_('Country'), max_length=255, blank=True, db_index=True)
    phone = models.CharField(_('Phone'), max_length=255, blank=True, db_index=True)
    fax = models.CharField(_('Fax'), max_length=255, blank=True, db_index=True)
    website = models.CharField(_('Website'), max_length=255, blank=True, db_index=True)
    default_email = models.CharField(_('Default Email'), max_length=255, blank=True, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'app_company'


##############  vtiger_industry  ###############################
class Terms(BaseModel):
    type = models.CharField(_('Type'), max_length=255, unique=True)
    content = models.TextField(_('Content'))

    class Meta:
        db_table = 'app_terms'


##############  vtiger_industry  ###############################
class Industry(BaseModel):
    title = models.CharField(_('Industry Name'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_industry'

##############  vtiger_rating  ###############################
class Rating(BaseModel):
    title = models.CharField(_('Rating Name'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_rating'

##############  vtiger_accounttype  ###############################
class AccountType(BaseModel):
    title = models.CharField(_('Account Type Name'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_account_type'


############## 客户信息表 ############################

class Organization(BaseModel):
    organization_name = models.CharField(_('Organization Name'), max_length=255, unique=True)
    website = models.CharField(_('Website'), max_length=255, blank=True, db_index=True)
    primary_phone = models.CharField(_('Primary Phone'), max_length=255, blank=True, db_index=True)
    ticker_symbol = models.CharField(_('Ticker Symbol'), max_length=255, blank=True, db_index=True)
    fax = models.CharField(_('Fax'), max_length=255, blank=True, db_index=True)
    member_of = models.ForeignKey("self", on_delete=models.PROTECT, null=True, blank=True, related_name="children",
                               verbose_name=_('Parent Organization'))

    secondary_phone = models.CharField(_('Secondary Phone'), max_length=255, blank=True, db_index=True)
    employees = models.CharField(_('Employees'), max_length=255, blank=True, db_index=True)
    primary_email = models.CharField(_('Primary Email'), max_length=255, blank=True, db_index=True)
    secondary_email = models.CharField(_('Secondary Email'), max_length=255, blank=True, db_index=True)
    ownership = models.CharField(_('Ownership'), max_length=255, blank=True, db_index=True)
    industry = models.ForeignKey(Industry, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Industry'))
    rating = models.ForeignKey(Rating, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Rating'))
    account_type = models.ForeignKey(AccountType, on_delete=models.PROTECT, null=True, blank=True,
                                     verbose_name=_('Account Type'))

    sic_code = models.CharField(_('SIC Code'), max_length=255, blank=True, db_index=True)
    email_opt_out = models.BooleanField(_('Email Opt Out'), default=False, blank=True, db_index=True)
    annual_revenue = models.CharField(_('Annual Revenue'), max_length=255, blank=True, db_index=True)
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))

    notify_owner = models.BooleanField(_('Notify Owner'), default=False, blank=True, db_index=True)
    billing_address = models.CharField(_('Billing Address'), max_length=255, blank=True, db_index=True)
    billing_po_box = models.CharField(_('Billing PO Box'), max_length=255, blank=True, db_index=True)
    billing_city = models.CharField(_('Billing City'), max_length=255, blank=True, db_index=True)
    billing_state = models.CharField(_('Billing State'), max_length=255, blank=True, db_index=True)
    billing_code = models.CharField(_('Billing Code'), max_length=255, blank=True, db_index=True)
    billing_country = models.CharField(_('Billing Country'), max_length=255, blank=True, db_index=True)

    shipping_address = models.CharField(_('Shipping Address'), max_length=255, blank=True, db_index=True)
    shipping_po_box = models.CharField(_('Shipping PO Box'), max_length=255, blank=True, db_index=True)
    shipping_city = models.CharField(_('Shipping City'), max_length=255, blank=True, db_index=True)
    shipping_state = models.CharField(_('Shipping State'), max_length=255, blank=True, db_index=True)
    shipping_postal_code = models.CharField(_('Shipping Postal Code'), max_length=255, blank=True, db_index=True)
    shipping_country = models.CharField(_('Shipping Country'), max_length=255, blank=True, db_index=True)
    description = models.CharField(_('Description'), max_length=255, blank=True, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'app_organization'


##############  vtiger_salutationtype  ###############################
class SalutationType(BaseModel):
    title = models.CharField(_('Salutation Type Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_salutation_type'


##############   vtiger_leadsource  ###############################
class LeadSource(BaseModel):
    title = models.CharField(_('Lead Source Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_lead_source'


##############   vtiger_leadstatus  ###############################
class LeadStatus(BaseModel):
    title = models.CharField(_('Lead Status Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_lead_status'


################### Leads #############################
class Leads(BaseModel):
    salutation = models.ForeignKey(SalutationType, on_delete=models.PROTECT, null=True, blank=True,
                                   verbose_name=_('Salutation Type'))
    first_name = models.CharField(_('First Name'), max_length=255, blank=True, db_index=True)
    last_name = models.CharField(_('Last Name'), max_length=255, blank=True, db_index=True)
    primary_phone = models.CharField(_('Primary Phone'), max_length=255, blank=True, db_index=True)
    company = models.CharField(_('Company'), max_length=255, blank=True, db_index=True)
    mobile_phone = models.CharField(_('Mobile Phone'), max_length=255, blank=True, db_index=True)
    designation = models.CharField(_('Designation'), max_length=255, blank=True, db_index=True)
    fax = models.CharField(_('Fax'), max_length=255, blank=True, db_index=True)

    lead_source = models.ForeignKey(LeadSource, on_delete=models.PROTECT, null=True, blank=True,
                                    verbose_name=_('Lead Source'))
    primary_email = models.CharField(_('Primary Email'), max_length=255, blank=True, db_index=True)
    industry = models.ForeignKey(Industry, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Industry'))

    website = models.CharField(_('Website'), max_length=255, blank=True, db_index=True)
    annual_revenue = models.DecimalField(_('Annual Revenue'), max_digits=20, default=0, decimal_places=2, db_index=True)
    lead_status = models.ForeignKey(LeadStatus, on_delete=models.PROTECT, null=True, blank=True,
                                    verbose_name=_('Lead Status'))

    number_of_employees = models.IntegerField(_('Number of Employees'), null=True, blank=True, db_index=True)
    rating = models.ForeignKey(Rating, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Rating'))

    secondary_email = models.CharField(_('Secondary Email'), max_length=255, blank=True, db_index=True)
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))

    email_opt_out = models.BooleanField(_('Email Opt Out'), default=False, blank=True, db_index=True)
    ################ Address Details ##############################################
    street = models.CharField(_('Street'), max_length=255, blank=True, db_index=True)
    po_box = models.CharField(_('PO Box'), max_length=255, blank=True, db_index=True)
    postal_code = models.CharField(_('Postal Code'), max_length=255, blank=True, db_index=True)
    city = models.CharField(_('City'), max_length=255, blank=True, db_index=True)
    country = models.CharField(_('Country'), max_length=255, blank=True, db_index=True)
    state = models.CharField(_('State'), max_length=255, blank=True, db_index=True)
    description = models.CharField(_('Description'), max_length=255, blank=True, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'app_leads'


############################### Contact ################
class Contact(BaseModel):
    salutation = models.ForeignKey(SalutationType, on_delete=models.PROTECT, null=True, blank=True,
                                   verbose_name=_('Salutation Type'))
    first_name = models.CharField(_('First Name'), max_length=255, blank=True, db_index=True)
    last_name = models.CharField(_('Last Name'), max_length=255, blank=True, db_index=True)
    office_phone = models.CharField(_('Office Phone'), max_length=255, blank=True, db_index=True)

    organization = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, blank=True,
                                     verbose_name=_('Organization'))

    mobile_phone = models.CharField(_('Mobile Phone'), max_length=255, blank=True, db_index=True)
    lead_source = models.ForeignKey(LeadSource, on_delete=models.PROTECT, null=True, blank=True,
                                    verbose_name=_('Lead Source'))
    home_phone = models.CharField(_('Home Phone'), max_length=255, blank=True, db_index=True)

    title = models.CharField(_('Title'), max_length=255, blank=True, db_index=True)
    secondary_phone = models.CharField(_('Secondary Phone'), max_length=255, blank=True, db_index=True)
    department = models.CharField(_('Department'), max_length=255, blank=True, db_index=True)
    fax = models.CharField(_('Fax'), max_length=255, blank=True, db_index=True)
    primary_email = models.CharField(_('Primary Email'), max_length=255, blank=True, db_index=True)
    date_of_birth = models.DateField(_('Date of Birth'), null=True, blank=True, db_index=True)

    assistant = models.CharField(_('Assistant'), max_length=255, blank=True, db_index=True)
    reports_to = models.ForeignKey("self", on_delete=models.PROTECT, null=True, blank=True, related_name="children",
                               verbose_name=_('Reports To'))

    assistant_phone = models.CharField(_('Assistant Phone'), max_length=255, blank=True, db_index=True)
    secondary_email = models.CharField(_('Secondary Email'), max_length=255, blank=True, db_index=True)
    email_opt_out = models.BooleanField(_('Email Opt Out'), default=False, blank=True, db_index=True)
    do_not_call = models.BooleanField(_('Do Not Call'), default=False, blank=True, db_index=True)
    reference = models.BooleanField(_('Reference'), default=False, blank=True, db_index=True)
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))
    notify_owner = models.BooleanField(_('Notify Owner'), default=False, blank=True, db_index=True)

    ################ Customer Portal Details ##########
    portal_user = models.BooleanField(_('Portal User'), default=False, blank=True, db_index=True)
    support_start_date = models.DateField(_('Support Start Date'), null=True, blank=True, db_index=True)
    support_end_date = models.DateField(_('Support End Date'), null=True, blank=True, db_index=True)

    ################  Address Details ###################
    mailing_street = models.CharField(_('Mailing Street'), max_length=255, blank=True, db_index=True)
    mailing_po_box = models.CharField(_('Mailing Po Box'), max_length=255, blank=True, db_index=True)
    mailing_city = models.CharField(_('Mailing City'), max_length=255, blank=True, db_index=True)
    mailing_state = models.CharField(_('Mailing State'), max_length=255, blank=True, db_index=True)
    mailing_zip = models.CharField(_('Mailing Zip'), max_length=255, blank=True, db_index=True)
    mailing_country = models.CharField(_('Mailing Country'), max_length=255, blank=True, db_index=True)

    other_street = models.CharField(_('Other Street'), max_length=255, blank=True, db_index=True)
    other_po_box = models.CharField(_('Other Po Box'), max_length=255, blank=True, db_index=True)
    other_city = models.CharField(_('Other City'), max_length=255, blank=True, db_index=True)
    other_state = models.CharField(_('Other State'), max_length=255, blank=True, db_index=True)
    other_zip = models.CharField(_('Other Zip'), max_length=255, blank=True, db_index=True)
    other_country = models.CharField(_('Other Country'), max_length=255, blank=True, db_index=True)
    description = models.CharField(_('Description'), max_length=255, blank=True, db_index=True)
    contact_image = models.FileField(_('Contact Image'), upload_to='uploads/', max_length=255)

    @property
    def full_name(self):
        """
        """
        return (self.first_name + ' ' + self.last_name).strip()

    class Meta:
        ordering = ['-id']
        db_table = 'app_contacts'


####### vtiger_quotestage #############
class QuoteStage(BaseModel):
    title = models.CharField(_('Quote Stage Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_quote_stage'


####### vtiger_carrier #############
class Carrier(BaseModel):
    title = models.CharField(_('Carrier Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_carrier'


class OrderModel(BaseModel):
    ### billing
    billing_user = models.CharField(_('Billing User'), max_length=255, null=True, blank=True, db_index=True)
    billing_org = models.CharField(_('Billing Org'), max_length=255, null=True, blank=True, db_index=True)
    billing_address = models.CharField(_('Billing Address'), max_length=255, null=True, blank=True, db_index=True)
    billing_po_box = models.CharField(_('Billing PO Box'), max_length=255, null=True, blank=True, db_index=True)
    billing_city = models.CharField(_('Billing City'), max_length=255, null=True, blank=True, db_index=True)
    billing_state = models.CharField(_('Billing State'), max_length=255, null=True, blank=True, db_index=True)
    billing_code = models.CharField(_('Billing Code'), max_length=255, null=True, blank=True, db_index=True)
    billing_country = models.CharField(_('Billing Country'), max_length=255, null=True, blank=True, db_index=True)
    billing_tel = models.CharField(_('Billing Tel'), max_length=255, null=True, blank=True, db_index=True)
    billing_fax = models.CharField(_('Billing Fax'), max_length=255, null=True, blank=True, db_index=True)
    billing_email = models.CharField(_('Billing Email'), max_length=255, null=True, blank=True, db_index=True)
    ### shipping
    shipping_user = models.CharField(_('Shipping User'), max_length=255, null=True, blank=True, db_index=True)
    shipping_org = models.CharField(_('Shipping Org'), max_length=255, null=True, blank=True, db_index=True)
    shipping_address = models.CharField(_('Shipping Address'), max_length=255, blank=True, db_index=True)
    shipping_po_box = models.CharField(_('Shipping PO Box'), max_length=255, blank=True, db_index=True)
    shipping_city = models.CharField(_('Shipping City'), max_length=255, blank=True, db_index=True)
    shipping_state = models.CharField(_('Shipping State'), max_length=255, blank=True, db_index=True)
    shipping_postal_code = models.CharField(_('Shipping Postal Code'), max_length=255, blank=True, db_index=True)
    shipping_country = models.CharField(_('Shipping Country'), max_length=255, blank=True, db_index=True)
    shipping_tel = models.CharField(_('Shipping Tel'), max_length=255, null=True, blank=True, db_index=True)
    shipping_fax = models.CharField(_('Shipping Fax'), max_length=255, null=True, blank=True, db_index=True)
    shipping_email = models.CharField(_('Shipping Email'), max_length=255, null=True, blank=True, db_index=True)

    class Meta:
        abstract = True

    @property
    def add_str(self):
        return '{user}{org}{address}{po_box}<br>{city}{state}{postal_code}{country}<br>{tel}{fax}{email}'

    @property
    def bill_address_html(self):
        """
        """
        return self.add_str.format(
            user=self.billing_user if self.billing_user else '',
            org='<br>' + self.billing_org if self.billing_org else '',
            address='<br>' + self.billing_address if self.billing_address else '',
            po_box=', ' + self.billing_po_box if self.billing_po_box else '',
            city=self.billing_city if self.billing_city else '',
            state=', ' + self.billing_state if self.billing_state else '',
            postal_code=' ' + self.billing_code if self.billing_code else '',
            country=', ' + self.billing_country if self.billing_country else '',
            tel='Tel: ' + self.billing_tel + '<br>' if self.billing_tel else '',
            fax='Fax: ' + self.billing_fax + '<br>' if self.billing_fax else '',
            email='Email: ' + self.billing_email + '<br>' if self.billing_email else ''
        )

    @property
    def shipping_address_html(self):
        """
        """
        return self.add_str.format(
            user=self.shipping_user if self.shipping_user else '',
            org='<br>' + self.shipping_org if self.shipping_org else '',
            address='<br>' + self.shipping_address if self.shipping_address else '',
            po_box=', ' + self.shipping_po_box if self.shipping_po_box else '',
            city=self.shipping_city if self.shipping_city else '',
            state=', ' + self.shipping_state if self.shipping_state else '',
            postal_code=' ' + self.shipping_postal_code if self.shipping_postal_code else '',
            country=', ' + self.shipping_country if self.shipping_country else '',
            tel='Tel: ' + self.shipping_tel + '<br>' if self.shipping_tel else '',
            fax='Fax: ' + self.shipping_fax + '<br>' if self.shipping_fax else '',
            email='Email: ' + self.shipping_email + '<br>' if self.shipping_email else ''
        )


##################### Quote ##############
class Quote(OrderModel):
    ### Quote Details
    subject = models.CharField(_('Subject'), max_length=255, blank=True, db_index=True)
    quote_stage = models.ForeignKey(QuoteStage, on_delete=models.PROTECT, verbose_name=_('Quote Stage'))

    valid_until = models.DateField(_('Valid Until'), max_length=255, null=True, blank=True, db_index=True)
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Contact'))
    carrier = models.ForeignKey(Carrier, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Carrier'))

    shipping = models.CharField(_('Shipping'), max_length=255, blank=True, db_index=True)
    # Inventory Manager 暂时放弃
    organization = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, blank=True,
                                     verbose_name=_('Organization'))
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))

    shipping_cost = models.DecimalField(_('Shipping Cost'), max_digits=20, default=0, decimal_places=2)
    tax = models.DecimalField(_('Tax'), max_digits=20, default=0, decimal_places=2)

    terms_conditions = models.TextField(_('Terms & Conditions'), blank=True)
    description = models.CharField(_('Description'), max_length=2000, blank=True, db_index=True)

    poFileLink = models.CharField(_('Po File Link'), max_length=2000, blank=True, db_index=True)
    poReplyComment = models.CharField(_('Po Reply Comment'), max_length=2000, blank=True, db_index=True)
    isPoValid = models.IntegerField(_('is Po Valid'), max_length=20, default=0, db_index=True)

    @property
    def slug(self):
        """
        """
        return 'Q1{}'.format(str(self.id).zfill(7))

    @property
    def get_total(self):
        amount = self.subtotal
        amount += self.shipping_cost
        amount += self.tax
        return amount

    @property
    def subtotal(self):
        subtotalAmount = 0
        for item in self.vector_set.all():
            subtotalAmount += item.unit_price * 1
        return subtotalAmount

    class Meta:
        ordering = ['-id']
        db_table = 'app_quotes'


####### vtiger_manufacturer #############
class Manufacturer(BaseModel):
    title = models.CharField(_('Manufacturer Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_manufacturer'


####### vtiger_productcategory #############
class ProductCategory(BaseModel):
    title = models.CharField(_('Product Category Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_product_category'


####### vtiger_glacct #############
class GLAccount(BaseModel):
    title = models.CharField(_('GL Account Title'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_gl_account'


############### products #########################
class Product(BaseModel):
    product_name = models.CharField(_('Product Name'), max_length=255, db_index=True)
    product_active = models.BooleanField(_('Product Active'), default=True, blank=True, db_index=True)
    part_number = models.CharField(_('Part Number'), max_length=255, blank=True, db_index=True)
    sales_start_date = models.DateField(_('Sales Start Date'), blank=True, db_index=True)

    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.PROTECT, null=True, blank=True,
                                     verbose_name=_('Manufacturer'))
    product_category = models.ForeignKey(ProductCategory, on_delete=models.PROTECT, null=True, blank=True,
                                         verbose_name=_('Product Category'))

    support_start_date = models.DateField(_('Support Start Date'), blank=True, db_index=True)
    sales_end_date = models.DateField(_('Sales End Date'), blank=True, db_index=True)
    support_expiry_date = models.DateField(_('Support Expiry Date'), blank=True, db_index=True)
    vendor_org = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, blank=True,
                                   verbose_name=_('Organization'))
    vendor_contact = models.ForeignKey(Contact, on_delete=models.PROTECT, null=True, blank=True,
                                       verbose_name=_('Contact'))

    website = models.CharField(_('Website'), max_length=255, blank=True, db_index=True)
    vendor_part_no = models.CharField(_('Vendor Part No'), max_length=255, blank=True, db_index=True)
    mfr_partno = models.CharField(_('Mfr PartNo'), max_length=255, blank=True, db_index=True)
    product_sheet = models.CharField(_('Product Sheet'), max_length=255, blank=True, db_index=True)
    serial_no = models.CharField(_('Serial No'), max_length=255, blank=True, db_index=True)
    gl_account = models.ForeignKey(GLAccount, on_delete=models.PROTECT, null=True, blank=True,
                                   verbose_name=_('GL Account'))
    ### Pricing Information
    unit_price = models.DecimalField(_('Unit Price'), max_digits=20, default=0, decimal_places=2, db_index=True)
    discount = models.IntegerField(_('Discount'), default=100)
    ### 库存信息先放弃
    with_tax = models.BooleanField(_('is with tax'), default=False)
    tax_rate = models.DecimalField(_('tax rate'), max_digits=20, default=0, decimal_places=2)
    product_image = models.FileField(_('Product Image'), upload_to='uploads/', max_length=255)

    description = models.CharField(_('Description'), max_length=255, blank=True, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'app_products'


####### vtiger_sostatus #############
class OrderStatus(BaseModel):
    title = models.CharField(_('Order Status'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_order_status'





############ Order ########################
class SalesOrder(OrderModel):
    subject = models.CharField(_('Subject'), max_length=255, blank=True, db_index=True)
    customer_no = models.CharField(_('Customer No'), max_length=255, blank=True, db_index=True)
    quote = models.ForeignKey(Quote, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Quote'))

    purchase_order = models.CharField(_('Purchase Order'), max_length=255, blank=True, db_index=True)
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Contact'))

    due_date = models.DateField(_('Due Date'), null=True, blank=True, db_index=True)
    carrier = models.ForeignKey(Carrier, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Carrier'))

    pending = models.CharField(_('Pending'), max_length=255, blank=True, db_index=True)
    status = models.ForeignKey(OrderStatus, on_delete=models.PROTECT, verbose_name=_('Order Status'))

    sales_commission = models.CharField(_('Sales Commission'), max_length=255, blank=True, db_index=True)
    excise_duty = models.CharField(_('Excise Duty'), max_length=255, blank=True, db_index=True)
    organization = models.ForeignKey(Organization, on_delete=models.PROTECT, verbose_name=_('Organization'))
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))
    ### Recurring Invoice Information 先放弃

    terms_conditions = models.TextField(_('Terms & Conditions'), blank=True, db_index=True)
    shipping_cost = models.DecimalField(_('Shipping Cost'), max_digits=20, default=0, decimal_places=2)
    tax = models.DecimalField(_('Tax'), max_digits=20, default=0, decimal_places=2)

    description = models.CharField(_('Description'), max_length=255, blank=True, db_index=True)

    @property
    def slug(self):
        """
        """
        result = 'C{}'
        if self.quote:
            result = result.format(re.sub('^Q', '', self.quote.subject))
        else:
            result = result.format(str(self.id).zfill(7))
        return result

    @property
    def get_total(self):
        amount = 0
        for item in self.vector_set.all():
            amount += item.unit_price * 1
        amount += self.shipping_cost
        amount += self.tax
        return amount

    class Meta:
        ordering = ['-id']
        db_table = 'app_sales_orders'


############ PackingSlip ########################
class PackingSlip(BaseModel):
    salesOrder = models.ForeignKey(SalesOrder)
    ship_status = models.IntegerField(_('ship status'), max_length=11, default=0, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'app_packing_slip'


def update_subject(sender, instance, created, **kwargs):
    if created:
        instance.subject = instance.slug
        instance.save()

post_save.connect(update_subject, sender=SalesOrder)

####### vtiger_invoicestatus #############
class InvoiceStatus(BaseModel):
    title = models.CharField(_('Invoice Status'), max_length=255, blank=True, db_index=True)
    sort_id = models.IntegerField(_('Sort ID'), db_index=True)

    class Meta:
        db_table = 'app_invoice_status'


############ Invoice ######################
class Invoice(OrderModel):
    subject = models.CharField(_('Subject'), max_length=255, blank=True, db_index=True)
    replaceInvoice = models.CharField(_('replace Invoice'), max_length=255, blank=True, db_index=True)
    sales_order = models.ForeignKey(SalesOrder, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Order Confirmation'))
    customer_no = models.CharField(_('Customer No'), max_length=255, blank=True, db_index=True)
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Contact'))

    invoice_date = models.DateField(_('Invoice Date'), null=True, blank=True, db_index=True)
    due_date = models.DateField(_('Due Date'), null=True, blank=True, db_index=True)
    purchase_order = models.CharField(_('Purchase Order'), max_length=255, blank=True, db_index=True)
    excise_duty = models.CharField(_('Excise Duty'), max_length=255, blank=True, db_index=True)

    sales_commission = models.CharField(_('Sales Commission'), max_length=255, blank=True, db_index=True)
    organization = models.ForeignKey(Organization, on_delete=models.PROTECT, verbose_name=_('Organization'))
    status = models.ForeignKey(InvoiceStatus, on_delete=models.PROTECT, null=True, blank=True, verbose_name=_('Status'))
    assigned_to = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=_('Assigned To'))

    terms_conditions = models.TextField(_('Terms & Conditions'), blank=True)
    shipping_cost = models.DecimalField(_('Shipping Cost'), max_digits=20, default=0, decimal_places=2)

    description = models.CharField(_('Description'), max_length=2000, blank=True, db_index=True)
    is_pain = models.BooleanField(_('Is Pain'), default=False)

    @property
    def slug(self):
        """
        """
        return 'N1{}'.format(str(self.id).zfill(7))

    @property
    def get_total(self):
        amount = 0
        for item in self.vector_set.all():
            amount += item.unit_price * 1
        amount += self.shipping_cost
        return amount

    class Meta:
        ordering = ['-id']
        db_table = 'app_invoice'


class Payment(BaseModel):
    invoice = models.ForeignKey(Invoice)
    account_paid = models.FloatField(_('account_paid'), db_index=True, max_length=22, blank=True)

    @property
    def paymentTotal(self):
        paymentTotal = 0.00
        paymentFilter = Payment.objects.filter(invoice=self.invoice)
        for item in paymentFilter:
            paymentTotal += item.account_paid
        return paymentTotal

    @property
    def nonPayment(self):
        nonPaymentFilter = Payment.objects.filter(created_on__lte=self.created_on, invoice=self.invoice)
        payment = 0.00
        for item in nonPaymentFilter:
            payment += item.account_paid
        nonPayment = float(self.invoice.get_total) - float(payment)
        return nonPayment

    class Meta:
        ordering = ['-id']
        db_table = 'app_payment'

post_save.connect(update_subject, sender=Invoice)


######### Vectors ###################
class Vector(BaseModel):
    """用户生成的 Vector 表, Vector 可以 share by 其他用户,目前采用 copy 的方式."""
    #through='PackingSlipVector',
    quote = models.ManyToManyField(Quote, through='QuoteVector', verbose_name=_('Quote'))
    sales_order = models.ManyToManyField(SalesOrder, through='OrderVector', verbose_name=_('Order Confirmation'))
    invoice = models.ManyToManyField(Invoice, through='InvoiceVector', verbose_name=_('Invoice'))
    packingSlip = models.ManyToManyField(PackingSlip, verbose_name=_('PackingSlip'))

    vector_id = models.CharField(_('Vector ID'), max_length=255, null=True, blank=True, unique=True)
    vector_name = models.CharField(_('Vector Name'), max_length=255)
    turnaround_time = models.CharField(_('Turnaround Time'), max_length=255, default='4-7')
    unit_price = models.DecimalField(_('Unit Price'), max_digits=20, default=0, decimal_places=2, db_index=True)
    url = models.CharField(_('Vector URL'), max_length=255)

    gb_text = models.TextField(_('Genbank Text'), blank=True)
    svg_text = models.TextField(_('Svg Text'), blank=True)
    ext_text = models.TextField(_('Ext Text'), blank=True)
    img_data = models.TextField(_('Img Data'), blank=True)

    def __unicode__(self):
        return self.vector_name

    # @property
    # def ship_status(self):
    #     """
    #     """
    #     print 111, self.packingSlip.filter(vector=self)
    #     return random.choice(['will_ship_in_future', 'shipped_this_time', 'shipped_previous'])

    @property
    def price(self):
        """
        """
        v = VectorExt(self)
        return v.price

    @property
    def tt(self):
        """
        """
        v = VectorExt(self)
        return v.tt

    @property
    def is_standard(self):
        """
        """
        v = VectorExt(self)
        return v.is_standard

    class Meta:
        ordering = ['-id']
        verbose_name_plural = _('Vectors')
        verbose_name = _('Vector')
        db_table = 'apps_vectors'


# class PackingSlipVector(models.Model):
#     vector = models.ForeignKey(Vector)
#     packingSlip = models.ForeignKey(PackingSlip)
#
#     class Meta:
#         ordering = ['-id']
#         db_table = 'apps_packingSlip_vector'


class QuoteVector(models.Model):
    quote = models.ForeignKey(Quote)
    vector = models.ForeignKey(Vector)

    class Meta:
        db_table = 'apps_vectors_quote'


class OrderVector(models.Model):
    salesorder = models.ForeignKey(SalesOrder)
    vector = models.ForeignKey(Vector)

    class Meta:
        db_table = 'apps_vectors_sales_order'


class InvoiceVector(models.Model):
    invoice = models.ForeignKey(Invoice)
    vector = models.ForeignKey(Vector)

    class Meta:
        db_table = 'apps_vectors_invoice'


class PromotionCode(BaseModel):
    promotion_code = models.CharField(_('Promotion Code'), max_length=255, unique=True)
    amount = models.DecimalField(_('Amount'), max_digits=20, default=0, decimal_places=2)
    discount_rate = models.DecimalField(_('Discount Rate'), max_digits=5, default=1, decimal_places=2)
    used = models.BooleanField('Used', default=False)

    class Meta:
        ordering = ['-id']
        db_table = 'app_promotion_code'


class BonusHistory(BaseModel):
    contact = models.ForeignKey(Contact)
    order = models.ForeignKey(SalesOrder)
    amount = models.DecimalField(_('Amount'), max_digits=20, default=0, decimal_places=2)

    class Meta:
        ordering = ['-id']
        db_table = 'app_bonus_history'


class Tags(BaseModel):
    tag = models.CharField('Tag', max_length=255)
    contact = models.ManyToManyField(Contact)
    organization = models.ManyToManyField(Organization)

    class Meta:
        ordering = ['-id']
        db_table = 'app_tags'


class Annotation(BaseModel):
    json_content = models.TextField(_('Content'), default='{}')
    obj_uuid = models.CharField(_('relate uuid'), max_length=36, blank=True, null=True, db_index=True)
    user_uuid = models.CharField(_('user uuid'), max_length=36, blank=True, null=True, db_index=True)

    class Meta:
        ordering = ['-id']
        db_table = 'user_annotation'

